package cn.com.transfer.services;

import cn.com.transfer.params.IcbcParams;
import cn.com.transfer.utils.Constants;
import cn.com.transfer.utils.IcbcInfo;
import cn.com.transfer.utils.IcbcNative;
import flexjson.JSONSerializer;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.entity.Record;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import static cn.com.transfer.utils.IcbcInfo.isRun;
import static cn.com.transfer.utils.IcbcInfo.schoolId;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * 圈存,金额限定500元
 */
public class Transfer extends MsgHandlerService {
    private Logger logger = LoggerFactory.getLogger(Transfer.class);

    @Override
    public String handler(Map params) {
        Map rtn = new HashMap();
        String accountNo = (String) params.get("accountNo");
        String terminalNo = (String) params.get("terminalNo");
        IcbcParams req = null, resp = null;
        try {
            if (!isRun) new SignIn().handler(new HashMap());
            checkArgument(isRun, "系统未签到");
            Record customer = dao.fetch("tb_Customer", Cnd.where("accountNo", "=", accountNo));
            checkCustomer(customer);
            String money = (String) params.get("money");
            BigDecimal oldMoney = (BigDecimal) customer.get("LeftMoney");


            //圈存返回空时 要做冲正
            checkNotNull(money, "交易金额不可为空");
            checkNotNull(terminalNo, "圈存机编号不可为空");
            Calendar ca = Calendar.getInstance();

            req = new IcbcParams(2);
            req.schoolCode = schoolId;
            req.transCode = Constants.ICBC_TRANS_SIGN_TRANSFER;
            req.transType = Constants.ICBC_TRANS_TYPE_RECHARGE;
            //0 正交易 1 反交易
            req.transMark = "0";
            req.transTime = String.format("%02d:%02d:%02d", ca.get(Calendar.HOUR_OF_DAY), ca.get(Calendar.MINUTE), ca.get(Calendar.SECOND));
            req.transDate = String.format("%04d-%02d-%02d", ca.get(Calendar.YEAR), ca.get(Calendar.MONTH) + 1, ca.get(Calendar.DAY_OF_MONTH));
            ca.add(Calendar.DAY_OF_MONTH, 1);
            req.accDate = String.format("%04d-%02d-%02d", ca.get(Calendar.YEAR), ca.get(Calendar.MONTH) + 1, ca.get(Calendar.DAY_OF_MONTH));
            req.terminalNo = terminalNo;
            req.transNo = getTransNo();
            req.yktNo = customer.getString("accountNo");
            req.bankCardNo = IcbcNative.encrypt(String.format("%-24s", customer.getString("bankAccNo")), 1);
            req.money = IcbcNative.encrypt(String.format("%-16s", money), 1);
            req.mac = req.genMac(1);

            resp = sendMessage(req);
            if (resp == null) reverse(req);     //异步冲正
            checkNotNull(resp, "连接服务器失败");
            checkArgument(resp.rtnCode.equals("00000"), Constants.msgMap.get(resp.rtnCode) == null ? resp.rtnMsg : Constants.msgMap.get(resp.rtnCode));

            //插入圈存记录
            Chain ch = Chain.make("accountNo", accountNo).add("bankNo", customer.getString("bankAccNo"))
                    .add("amount", money).add("accDate", ca.getTime()).add("transNo", req.transNo)
                    .add("bankTransNo", resp.bankTransNo).add("terminalNo", terminalNo);
            ca.add(Calendar.DAY_OF_MONTH, -1);
            ch.add("serviceAt", ca.getTime());
            dao.insert("icbcQCLog", ch);

            rtn.put("success", true);
            rtn.put("transNo", req.transNo);
        } catch (Exception e) {
            logger.error("error in Transfer", e);
            rtn.put("success", false);
            rtn.put("msg", e.getMessage() != null ? e.getMessage() : e.toString());
            if (resp != null) {
                if ("00000".equals(resp.rtnCode)) reverse(req);
                if ("9003".equals(resp.rtnCode)) IcbcInfo.isRun = false;
            }
        }

        return new JSONSerializer().serialize(rtn);
    }

    private void reverse(final IcbcParams req) {
        new Thread(new Runnable() {
            public void run() {
                try {
                    Calendar cal = Calendar.getInstance();
                    req.transCode = Constants.ICBC_TRANS_SIGN_REVER;
                    req.transMark = "1";
                    req.transTime = String.format("%02d%02d%02d", cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
                    req.transDate = String.format("%04d%02d%02d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
                    cal.add(Calendar.DAY_OF_MONTH, 1);
                    req.accDate = String.format("%04d%02d%02d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
                    req.oldTransNo = req.transNo;
                    req.transNo = getTransNo();
                    req.mac = req.genMac(1);
                    IcbcParams resp = sendMessage(req);

                    if (resp != null) {
                        logger.info("订单交易失败，冲正结果代码 {}", resp.rtnCode);
                    }
                } catch (Exception e) {
                    logger.error("error in transfer.reverseTrans", e);
                }
            }
        }).start();
    }
}
